package com.whfc.fse.queue;

import com.alibaba.fastjson.JSON;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.NetState;
import com.whfc.common.util.JSONUtil;
import com.whfc.fse.dao.FseCrawlerDataMapper;
import com.whfc.fse.dao.FseCrawlerMapper;
import com.whfc.fse.dto.FseCrawlerDataDTO;
import com.whfc.fse.dto.FseWarnDTO;
import com.whfc.fse.entity.FseCrawler;
import com.whfc.fse.entity.FseCrawlerData;
import com.whfc.fse.entity.FseCrawlerDataLog;
import com.whfc.fse.enums.FseType;
import com.whfc.fse.enums.FseWarnRuleType;
import com.whfc.fse.manager.FseWarnMgr;
import com.whfc.influx.dao.FseCrawlerDataLogDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * 处理履带吊实时数据
 *
 * @author qzexing
 * @version 1.0
 * @date 2021/11/2 10:07
 */
@Component
@RabbitListener(queuesToDeclare = {@Queue(name = QueueConst.FSE_CRAWLER_CURRENT_DATA)}, concurrency = "1-2",containerFactory = "baseFactory")
public class FseCrawlerRealDataQueueListener {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 履带吊报警标志
     */
    private static final Integer WARN_FLAG = 1;

    @Autowired
    private FseCrawlerMapper fseCrawlerMapper;

    @Autowired
    private FseCrawlerDataMapper fseCrawlerDataMapper;

    @Autowired
    private FseCrawlerDataLogDao fseCrawlerDataLogDao;

    @Autowired
    private FseWarnMgr fseWarnMgr;

    @RabbitHandler
    public void handle(String msg) {
        logger.info("队列同步履带吊实时数据,msg:{}", msg);
        try {
            //数据验证
            FseCrawlerDataDTO fseCrawlerDataDTO = JSONUtil.parseObject(msg, FseCrawlerDataDTO.class);
            String platform = fseCrawlerDataDTO.getPlatform();
            String sn = fseCrawlerDataDTO.getSn();
            FseCrawler fseCrawler = fseCrawlerMapper.selectBySnAndPlatform(sn, platform);
            if (fseCrawler == null) {
                logger.info("未找到设备sn:{}", sn);
                return;
            }
            Integer crawlerId = fseCrawler.getId();
            fseCrawlerDataDTO.setCrawlerId(crawlerId);

            //保存实时数据
            FseCrawlerData fseCrawlerData = fseCrawlerDataMapper.selectByCrawlerId(crawlerId);
            if (fseCrawlerData == null) {
                fseCrawlerData = new FseCrawlerData();
                fseCrawlerData.setCrawlerId(fseCrawler.getId());
                fseCrawlerDataMapper.insertSelective(fseCrawlerData);
            }
            BeanUtils.copyProperties(fseCrawlerDataDTO, fseCrawlerData);
            fseCrawlerData.setProbeDistances(JSONUtil.toString(fseCrawlerDataDTO.getProbeDistanceList()));
            fseCrawlerData.setProbeDistanceWarns(JSONUtil.toString(fseCrawlerDataDTO.getProbeDistanceWarnList()));
            fseCrawlerDataMapper.updateByPrimaryKeySelective(fseCrawlerData);

            //保存历史数据
            FseCrawlerDataLog fseCrawlerDataLog = new FseCrawlerDataLog();
            BeanUtils.copyProperties(fseCrawlerData, fseCrawlerDataLog);
            fseCrawlerDataLog.setTime(fseCrawlerDataDTO.getTime());
            logger.info("履带吊保存历史数据：{}",fseCrawlerDataLog.toString());
            fseCrawlerDataLogDao.insert(fseCrawlerDataLog);

            //更新在线状态
            fseCrawler.setNetState(NetState.ONLINE.getValue());
            fseCrawlerMapper.updateByPrimaryKeySelective(fseCrawler);

            //处理报警信息
            handleWarn(fseCrawler, fseCrawlerDataDTO);
        } catch (Exception e) {
            logger.error("队列同步履带吊实时数据出错", e);
        }
    }

    /**
     * 处理报警信息
     *
     * @param crawlerData 履带吊数据
     * @param fseCrawler  履带吊信息
     */
    private void handleWarn(FseCrawler fseCrawler, FseCrawlerDataDTO crawlerData) {

        //履带吊回转报警
        Date time = crawlerData.getTime();
        if (WARN_FLAG.equals(crawlerData.getTurnWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_TURN;
            String triggerValue = crawlerData.getTurnAngle().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊主钩高度报警
        if (WARN_FLAG.equals(crawlerData.getMainHookHeightWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_MAIN_HOOK_HEIGHT;
            String triggerValue = crawlerData.getMainHookHeight().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊主钩重量报警
        if (WARN_FLAG.equals(crawlerData.getMainHookWeightWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_MAIN_HOOK_WEIGHT;
            String triggerValue = crawlerData.getMainHookWeight().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊副钩高度报警
        if (WARN_FLAG.equals(crawlerData.getViceHookHeightWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_VICE_HOOK_HEIGHT;
            String triggerValue = crawlerData.getViceHookHeight().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊副钩重量报警
        if (WARN_FLAG.equals(crawlerData.getViceHookWeightWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_VICE_HOOK_WEIGHT;
            String triggerValue = crawlerData.getViceHookWeight().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊防后倾报警
        if (WARN_FLAG.equals(crawlerData.getDipAngleWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_DIP_ANGLE;
            String triggerValue = crawlerData.getDipAngle().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊风速报警
        if (WARN_FLAG.equals(crawlerData.getWindSpeedWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_WIND_SPEED;
            String triggerValue = crawlerData.getWindSpeed().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊非正常操作报警
        if (WARN_FLAG.equals(crawlerData.getAbnormalOpWarn())) {
            FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_ABNORMAL_OP;
            String triggerValue = crawlerData.getAction().toString();
            this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
        }
        //履带吊防撞探头报警
        List<Integer> probeDistanceWarnList = crawlerData.getProbeDistanceWarnList();
        if (probeDistanceWarnList != null) {
            long warnCnt = probeDistanceWarnList.stream().count();
            if (warnCnt > 0) {
                FseWarnRuleType fseWarnRuleType = FseWarnRuleType.CRAWLER_ANTI_COLLISION;
                String triggerValue = JSON.toJSONString(crawlerData.getProbeDistanceList());
                this.handleWarn(fseCrawler, fseWarnRuleType, triggerValue, time);
            }
        }
    }

    /**
     * 处理报警信息
     *
     * @param fseCrawler
     * @param fseWarnRuleType
     * @param triggerValue
     * @param triggerTime
     */
    private void handleWarn(FseCrawler fseCrawler, FseWarnRuleType fseWarnRuleType, String triggerValue, Date triggerTime) {
        FseWarnDTO fseWarnDTO = new FseWarnDTO();
        fseWarnDTO.setFseType(FseType.CRAWLER);
        fseWarnDTO.setFseWarnRuleType(fseWarnRuleType);
        fseWarnDTO.setDeptId(fseCrawler.getDeptId());
        fseWarnDTO.setCode(fseCrawler.getCode());
        fseWarnDTO.setTriggerObjectId(fseCrawler.getId());
        fseWarnDTO.setTriggerTime(triggerTime);
        fseWarnDTO.setTriggerValue(triggerValue);
        fseWarnMgr.handleFseWarn(fseWarnDTO);
    }
}
